#if defined mystreamer_inc
#endscript
#endif
#define mystreamer_inc

#include <a_samp>

#tryinclude num_players

#if !defined MAX_STREAM_OBJECTS
#define MAX_STREAM_OBJECTS 50
#endif

#if !defined VIEW_DISTANCE
#define VIEW_DISTANCE 300.0
#endif

#define XY_PRECISION 1000
#define Z_PRECISION 10000
#define OW_PRECISION 10

enum objstruct
{
	e_modelid,
	e_x,
	e_y,
	e_z,
	e_ox, // offsets
	e_oy,
	e_oz,
	e_ow,
	e_rx, // rotating
	e_ry,
	e_rz,
	e_objectid[MAX_PLAYERS] //
};

static streamer_objects[MAX_STREAM_OBJECTS][objstruct];

static object_count = -1;

forward StreamObjects();

public StreamObjects()
{
	// Comment the line below if you're not using gActivePlayers var.
	if(!GetPlayersAmount()) return false;
	new Float:xx, Float:yy, Float:zz;
	for(new playerid=0; playerid<MAX_PLAYERS; playerid++) if(GetPlayerPos(playerid, xx, yy, zz))
	{
		StreamRangeObjects(xx, yy, zz, VIEW_DISTANCE, playerid);
	}
	return true;
}

StreamRangeObjects(Float:x, Float:y, Float:z, Float:range, extra)
{
	new Float:offset = x * x + y * y + z * z;
	new const Float:sqrange = range * range;
	for(new j = 0; j <= object_count; ++j)
	{
		// Calculate the distance to the object.
		offset = offset + streamer_objects[j][e_ow] / OW_PRECISION + x * (streamer_objects[j][e_ox] / XY_PRECISION) +
		y * (streamer_objects[j][e_oy] / XY_PRECISION) + z * (streamer_objects[j][e_oz] / Z_PRECISION);
		// We now have the SQUARED distance to this object.
		if (offset < sqrange)
		{
			ShowStreamObjectForPlayer(j, extra);
		}
		else
		{
			HideStreamObjectForPlayer(j, extra);
		}
	}
}


ShowStreamObjectForPlayer(sobjectid, playerid)
{
	if(streamer_objects[sobjectid][e_objectid][playerid] == 0)
	{
		streamer_objects[sobjectid][e_objectid][playerid] =
			CreatePlayerObject(playerid, streamer_objects[sobjectid][e_modelid],
				streamer_objects[sobjectid][e_x] / XY_PRECISION, streamer_objects[sobjectid][e_y] / XY_PRECISION, streamer_objects[sobjectid][e_z] / Z_PRECISION,
				streamer_objects[sobjectid][e_rx] / XY_PRECISION, streamer_objects[sobjectid][e_ry] / XY_PRECISION, streamer_objects[sobjectid][e_rz] / Z_PRECISION);
		if(streamer_objects[sobjectid][e_objectid][playerid] == INVALID_OBJECT_ID)
			streamer_objects[sobjectid][e_objectid][playerid] = 0;
		return true;
	}
	else
		return false;
}


HideStreamObjectForPlayer(sobjectid, playerid)
{
	if(streamer_objects[sobjectid][e_objectid][playerid] != 0)
	{
		DestroyPlayerObject(playerid, streamer_objects[sobjectid][e_objectid][playerid]);
		streamer_objects[sobjectid][e_objectid][playerid] = 0;
		return true;
	}
	else
		return false;
}

stock CreateStreamObject(modelid, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz)
{
	new Float:ox, Float:oy, Float:oz;
	if(object_count >= MAX_STREAM_OBJECTS) return(-1);
	// Get the offset from the last object.
	if (object_count == -1)
	{
		ox = 0.0;
		oy = 0.0;
		oz = 0.0;
	}
	else
	{
		ox = streamer_objects[object_count][e_x]/XY_PRECISION;
		oy = streamer_objects[object_count][e_y]/XY_PRECISION;
		oz = streamer_objects[object_count][e_z]/Z_PRECISION;
	}
	new
		Float:dx = ox - x,
		Float:dy = oy - y,
		Float:dz = oz - z;
	++object_count;
	// Store the offsets.
	streamer_objects[object_count][e_ox] = floatround(2 * dx * XY_PRECISION);
	streamer_objects[object_count][e_oy] = floatround(2 * dy * XY_PRECISION);
	streamer_objects[object_count][e_oz] = floatround(2 * dz * Z_PRECISION);
	// Calculate the main constant.
	streamer_objects[object_count][e_ow] = floatround(
	(	(dx * dx + dy * dy + dz * dz) - 2 *
		(ox * dx + oy * dy + oz * dz)
	) * OW_PRECISION);
	// Store the other data.
	streamer_objects[object_count][e_x] = floatround(x * XY_PRECISION);
	streamer_objects[object_count][e_y] = floatround(y * XY_PRECISION);
	streamer_objects[object_count][e_z] = floatround(z * Z_PRECISION);
	streamer_objects[object_count][e_rx] = floatround(rx * XY_PRECISION);
	streamer_objects[object_count][e_ry] = floatround(ry * XY_PRECISION);
	streamer_objects[object_count][e_rz] = floatround(rz * Z_PRECISION);
	streamer_objects[object_count][e_modelid] = modelid;
	return(object_count);
}

stock PopStreamObject() { return(--object_count); }

stock GetStreamObjectsCount() { return(object_count+1); }

/*
mystream_ongamemodeinit()
{
	//for(new i=0; i<MAX_PLAYERS; i++)
		//e_objectid
}*/




